#include "TaskScheduler.h"
TaskScheduler::TaskScheduler()
{
}
TaskScheduler::~TaskScheduler()
{
	StopRun();
}

int64_t TaskScheduler::getCurrentTicket()
{
	//std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
	//std::chrono::steady_clock::time_point t11;
	//int64_t duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t11).count();
	//int64_t duration = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t11).count();
	return  std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
int32_t TaskScheduler::StartRun()
{
	m_loopThread = new std::thread(&TaskScheduler::RunLoop, this);
	std::unique_lock<std::mutex> lock(_mutex);
	_condition.wait(lock, [this]() { return m_bStart == true; });

	if (m_loopThread)
	{
		return 0;
	}
	return -1;

}
void TaskScheduler::StopRun()
{
	m_bExitThread = true;
	{
		std::unique_lock<std::mutex> lock(_mutex);
		_queue.push_back([]() {int a; });
	}
	_condition.notify_one();

	if (m_loopThread)
	{
		m_loopThread->join();
		delete m_loopThread;
		m_loopThread = 0;
	}
}

int64_t TaskScheduler::AddTimer(int64_t iDelay, std::function<bool()> fcb)
{

	//using RetType = decltype(int32_t(Timer&&)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
#if 0
	auto t_timer = std::make_shared<Timer>(iDelay, fcb);

	auto task = std::make_shared<std::packaged_task<int64_t(std::shared_ptr<Timer>)>>(
		bind(&TaskScheduler::addTimerInner, this, (t_timer)));


	std::future<int64_t> future = task->get_future();

	{
		std::lock_guard<std::mutex> lock(_mutex);
		_queue.push_back([task]() {
			std::shared_ptr<Timer> a;
			(*task)(a);
			});
	}
	_condition.notify_one();
	int32_t ret = future.get();
	return ret;
#else

#endif

	Event tEvent;
	auto t_timer = std::make_shared<Timer>(iDelay, fcb);
	int64_t t_timer_id = 0;
	InvokTask([this, &t_timer, &t_timer_id]()
		{
			m_iTimerId++;
			t_timer->m_iTimerId = m_iTimerId;
			t_timer_id = m_iTimerId;
			uint64_t time_line = getCurrentTicket() + t_timer->m_iDelay;
			m_delayTask.emplace(time_line, std::move(t_timer));
		}
	);
	return t_timer_id;
}

void TaskScheduler::PostTask(Task task)
{
	// 调用线程和将要打入的线程是同一个
	if (_loopThreadId == std::this_thread::get_id())
	{
		// 原地执行就可以
		task();
	}
	{
		std::unique_lock<std::mutex> lock(_mutex);
		Event tEvent;
		_queue.push_back([task]() {
			task();

			});
	}
	_condition.notify_one();
}

void TaskScheduler::InvokTask(Task task)
{
	// 调用线程和将要打入的线程是同一个
	if (_loopThreadId == std::this_thread::get_id())
	{
		// 原地执行就可以
		task();
	}

	Event tEvent;
	{
		std::unique_lock<std::mutex> lock(_mutex);
		_queue.push_back([task, &tEvent]() {
			task();
			tEvent.Set(0);
			});
	}
	_condition.notify_one();
	printf("Wait before \n");
	tEvent.Wait();
}

int32_t TaskScheduler::DelTimer(int64_t timerId)
{

#if 0
	auto task = std::make_shared<std::packaged_task<int32_t(int32_t)>>(
		std::bind(&TaskScheduler::delTimerInner, this, (timerId)));

	std::future<int32_t> future = task->get_future();

	{
		std::lock_guard<std::mutex> lock(_mutex);
		_queue.push_back([task]() {
			(*task)(0);
			});

	}
	_condition.notify_one();
	int32_t ret = future.get();
	return ret;
#else

#endif

	int ret = -1;
	InvokTask([this, timerId, &ret]()
		{
			std::multimap<uint64_t, std::shared_ptr<Timer> >::iterator it = m_delayTask.begin();
			for (; it != m_delayTask.end();)
			{
				std::shared_ptr<Timer> pTimer = it->second;
				if (pTimer->m_iTimerId == timerId)
				{
					it = m_delayTask.erase(it);
					ret = 0;
					return;
				}
				else
				{
					it++;
				}
			}

		});
	return ret;
}


void TaskScheduler::RunLoop()
{
	_loopThreadId = std::this_thread::get_id();
	m_bStart = true;
	_condition.notify_one();

	while (!m_bExitThread)
	{
		int64_t delay = getMinDelay(); // 处理定时器任务

		std::list<Task> t_queue;
		{
			std::unique_lock<std::mutex> lock(_mutex);
			//_condition.wait_for(lock, std::chrono::milliseconds(delay), [this]() { return !_queue.empty(); });
			_condition.wait_for(lock, std::chrono::microseconds(delay), [this]() { return !_queue.empty(); });
			if (!_queue.empty())
			{
				t_queue.swap(_queue);

			}
		}
		// 处理任务
		if (!t_queue.empty())
		{
			for (std::list<Task>::iterator it = t_queue.begin(); it != t_queue.end(); it++)
			{
				Task task = *it;
				task();
			}
			t_queue.clear();
		}
	}

}



int64_t TaskScheduler::getMinDelay() {
	auto it = m_delayTask.begin();
	if (it == m_delayTask.end()) {
		//没有剩余的定时器了
		return 0;
	}
	auto now = getCurrentTicket();
	if (it->first > now) {
		//所有任务尚未到期
		return it->first - now;
	}
	//执行已到期的任务并刷新休眠延时
	return flushDelayTask(now);
}

int64_t TaskScheduler::flushDelayTask(uint64_t now_time) {

	//printf("############# sleep :%llu \n", now_time);
	decltype(m_delayTask) taskCopy;
	taskCopy.swap(m_delayTask);
	uint64_t start = getCurrentTicket();
	for (auto it = taskCopy.begin(); it != taskCopy.end() && it->first <= now_time; it = taskCopy.erase(it)) {
		//已到期的任务
		try {
			//auto next_delay = (*(it->second))();
			std::shared_ptr<Timer>  pTimer = it->second;
			if (pTimer->m_cb)
			{
				bool ret = pTimer->m_cb();
				if (ret)
				{
					m_delayTask.emplace(pTimer->m_iDelay + now_time, std::move(it->second));
				}
			}
		}
		catch (std::exception& ex) {
			//ErrorL << "EventPoller执行延时任务捕获到异常:" << ex.what();
		}
	}
	uint64_t end = getCurrentTicket();
	int64_t useTime = end - start;
	if (useTime > 11)
	{
		//printf("timers_poll::flushDelayTask useTimer = %d \n", useTime);
	}

	taskCopy.insert(m_delayTask.begin(), m_delayTask.end());
	taskCopy.swap(m_delayTask);

	auto it = m_delayTask.begin();
	if (it == m_delayTask.end()) {
		//没有剩余的定时器了
		return 0;
	}
	//最近一个定时器的执行延时

	int64_t t_sleep = it->first - getCurrentTicket();
	if (t_sleep < -1)
	{
		printf("timers_poll::flushDelayTask  t_sleep = %lld  \n", t_sleep);
	}
	return t_sleep > 0 ? t_sleep : 0;

}

